/**
 * 音频处理器单元测试
 */

import audioProcessor from '../../src/core/audioProcessor';

const {
  initAudioProcessor,
  connectMicrophoneStream,
  disconnectMicrophoneStream,
  startLevelAnalysis,
  stopLevelAnalysis,
  setGain,
  getGain,
  startPlayback,
  stopPlayback,
  registerAudioDataCallback,
  setProcessingConfig,
  getProcessingConfig,
  getMicrophoneStream
} = audioProcessor;

// 导入清理函数
const { clearMocks, restorePerformanceNow } = require('../setup');

// 模拟AudioProcessingEvent
const createMockAudioProcessingEvent = () => {
  return {
    inputBuffer: {
      getChannelData: () => {
        const buffer = new Float32Array(4096);
        for (let i = 0; i < buffer.length; i++) {
          buffer[i] = (Math.random() * 2) - 1; // -1.0 到 1.0 之间的随机值
        }
        return buffer;
      },
      sampleRate: 44100,
      length: 4096,
      numberOfChannels: 1
    },
    outputBuffer: {
      getChannelData: () => new Float32Array(4096),
      sampleRate: 44100,
      length: 4096,
      numberOfChannels: 1
    }
  };
};

describe('音频处理器测试', () => {
  let audioContext;
  let mockStream;
  
  beforeEach(() => {
    // 创建模拟的音频上下文和媒体流
    audioContext = new AudioContext();
    const audioTrack = new MediaStreamTrack('audio');
    mockStream = new MediaStream([audioTrack]);
    
    // 初始化音频处理器
    initAudioProcessor();
  });
  
  afterEach(() => {
    // 断开所有连接
    disconnectMicrophoneStream();
    // 清理模拟
    clearMocks();
  });
  
  afterAll(() => {
    // 恢复原始函数
    restorePerformanceNow();
  });
  
  test('初始化音频处理器', () => {
    expect(initAudioProcessor).not.toThrow();
  });
  
  test('连接麦克风流', async () => {
    const result = await connectMicrophoneStream(mockStream);
    expect(result).toBe(true);
  });
  
  test('断开麦克风流', () => {
    connectMicrophoneStream(mockStream);
    expect(disconnectMicrophoneStream).not.toThrow();
  });
  
  test('开始音量分析', () => {
    connectMicrophoneStream(mockStream);
    expect(startLevelAnalysis).not.toThrow();
  });
  
  test('停止音量分析', () => {
    connectMicrophoneStream(mockStream);
    startLevelAnalysis();
    expect(stopLevelAnalysis).not.toThrow();
  });
  
  test('设置增益', () => {
    const testGain = 0.5;
    setGain(testGain);
    expect(getGain()).toBe(testGain);
  });
  
  test('增益值应该在0到1之间', () => {
    setGain(1.5);
    expect(getGain()).toBe(1.0);
    
    setGain(-0.5);
    expect(getGain()).toBe(0.0);
  });
  
  test('开始和停止回放', () => {
    const buffer = new ArrayBuffer(1024);
    expect(() => startPlayback(buffer)).not.toThrow();
    expect(() => stopPlayback()).not.toThrow();
  });
  
  test('注册音频数据回调', async () => {
    const mockCallback = jest.fn();
    registerAudioDataCallback(mockCallback);
    
    // 连接麦克风流
    await connectMicrophoneStream(mockStream);
    
    // 手动触发音频处理事件
    const scriptProcessor = audioContext.createScriptProcessor(4096, 1, 1);
    if (scriptProcessor.onaudioprocess) {
      scriptProcessor.onaudioprocess(createMockAudioProcessingEvent());
    }
    
    // 由于我们无法直接触发onaudioprocess事件，这里我们只测试注册不抛出错误
    expect(registerAudioDataCallback).not.toThrow();
  });
  
  test('设置和获取处理配置', () => {
    const testConfig = {
      enableProcessing: true,
      sampleRate: 16000,
      bufferSize: 2048,
      channelCount: 1
    };
    
    setProcessingConfig(testConfig);
    const config = getProcessingConfig();
    
    expect(config).toEqual(expect.objectContaining({
      enableProcessing: true,
      sampleRate: 16000,
      bufferSize: 2048,
      channelCount: 1
    }));
  });
  
  test('获取麦克风流', async () => {
    await connectMicrophoneStream(mockStream);
    const stream = getMicrophoneStream();
    expect(stream).toBe(mockStream);
  });
  
  test('处理无效的麦克风流', async () => {
    const result = await connectMicrophoneStream(null);
    expect(result).toBe(false);
  });
  
  test('在未连接麦克风的情况下获取麦克风流', () => {
    disconnectMicrophoneStream();
    const stream = getMicrophoneStream();
    expect(stream).toBeNull();
  });
  
  test('在未连接麦克风的情况下开始音量分析', () => {
    disconnectMicrophoneStream();
    expect(startLevelAnalysis).not.toThrow();
  });
  
  test('在未连接麦克风的情况下停止音量分析', () => {
    disconnectMicrophoneStream();
    expect(stopLevelAnalysis).not.toThrow();
  });
}); 